package com.gpt.article.service.impl.taskHandle.task;

import chatgpt.ChatGPT;
import chatgpt.entity.chat.ChatCompletion;
import chatgpt.entity.chat.ChatCompletionResponse;
import chatgpt.entity.chat.Message;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.gpt.article.domain.GptTopicTitle;
import com.gpt.article.domain.GptUseToken;
import com.gpt.article.domain.TxtClassify;
import com.gpt.article.service.IGptTopicTitleService;
import com.gpt.article.service.ITxtClassifyService;
import com.gpt.article.service.impl.taskHandle.GenTask;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.GptTxtClassDetail;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;

@Service
public class GenTxtClassifyTasker {

    private static Logger logger = LoggerFactory.getLogger(GenTxtClassifyTasker.class);
    private static ChatCompletion chatCompletion;

    private static ITxtClassifyService iTxtClassifyService;

    @Autowired
    public void setITxtClassifyService(ITxtClassifyService iTxtClassifyService) {
        GenTxtClassifyTasker.iTxtClassifyService = iTxtClassifyService;
    }

    /**
     * 生成内容分类
     * 分为两种情况 使用已有分类项  或者 根据系统生成模式
     * @param txtClassify
     * @param chatGPT
     * @param genTask
     * @param taskId
     * @return
     */
//    [{"title":"12","genPrompts":"12"},{"title":"33","genPrompts":"33"}]
    public boolean genContent(TxtClassify txtClassify, ChatGPT chatGPT, GenTask genTask, Long taskId){
//        String content = txtClassify.getTxtContent();
        String creteBy = genTask.getAcc();
        String model_conf = txtClassify.getModelName();
        String comstomId = txtClassify.getTxtId();
        Map<String,Object> psMap = genTask.getPsMap();



        long startTime = System.currentTimeMillis();

        Map<String,Object> map = startGen(chatGPT,txtClassify,psMap);

        long endTime = System.currentTimeMillis();
        long elapsedTime = endTime - startTime;
        logger.info("生成成功！耗时：{}",elapsedTime);

        //提取生成内容
        String useModelName  =String.valueOf(map.get("useModelName"));
        String classContent  =String.valueOf(map.get("classContent"));
        Integer countToken  =Integer.valueOf(String.valueOf(map.get("tokenCount")));
        Integer promptCount  =Integer.valueOf(String.valueOf(map.get("promptCount")));
        Integer completionCount  =Integer.valueOf(String.valueOf(map.get("completionCount")));


        //插入token
        GptUseToken gptUseToken = new GptUseToken();
        gptUseToken.setElapsedTime(elapsedTime);
        gptUseToken.setModuleName("内容分类");
        gptUseToken.setTaskId(taskId);
        gptUseToken.setUseDate(DateUtils.parseDateToStr("yyyy-MM-dd",new Date()));
        gptUseToken.setUseModel(txtClassify.getModelName());
//        gptUseToken.setPayMoney(useToken.getPayMoney());
        gptUseToken.setTotalTokens(countToken);
        gptUseToken.setPromptTokens(promptCount);
        gptUseToken.setCompletionTokens(completionCount);
        gptUseToken.setCreateBy(creteBy);
        Long useId = new OptUseTokenDb().insertTokenInfo(gptUseToken);
        System.out.println("insertTokenInfo--tokenId == = "+useId);
        Long titleId = upTxtInfo(creteBy,useId,countToken,useModelName,comstomId,classContent,txtClassify.getId(), genTask.getTaskNum(), taskId);
        gptUseToken.setId(useId);
        gptUseToken.setBusinessId(titleId);
        new OptUseTokenDb().updateTolenInfo(gptUseToken);
        return true;
    }


    public Long upTxtInfo(String creteBy,Long tokenId,
                                   Integer countToken,String model_conf,
                                   String comstomId,String classContent,
                                   Long artId,
                                   Integer taskNum,Long taskId){
        TxtClassify txtClassify = new TxtClassify();
        txtClassify.setClassNames(classContent);
        txtClassify.setClassIds(comstomId);
        txtClassify.setId(artId);
        txtClassify.setUseToken(countToken);
        txtClassify.setModelName(model_conf);
        txtClassify.setCreateBy(creteBy);
        txtClassify.setUseTokenId(tokenId);
        txtClassify.setUpdateTime(DateUtils.getNowDate());
        txtClassify.setStatus("1");
        Long id = iTxtClassifyService.updateTxtClassify(txtClassify);
        new XiGaoTasker().upTask(taskId,0,0,taskNum,"2");
        return id;
    }


    /**
     * 处理提示词参数
     * @param content
     * @param psMap
     * @return
     */
    public String getPrompts(String content,Map<String,Object> psMap){
        Boolean useClassItem = Boolean.valueOf(String.valueOf(psMap.get("useClassswitch")));
        String classInfos = String.valueOf(psMap.get("classinfo"));

        Long itemId = Long.valueOf(String.valueOf(psMap.get("itemId")));
        String promptsContent = "";
        if(useClassItem){
            promptsContent = "我需要你根据我提供的分类信息的json， 将提供的内容进行分类,如果存在多级需要根据多级分类，不需要任何解释描述，直接回答彼标准的层级json分类信息，选择最合适分类仅需两层级即可，例如：{\"name\":\"主类目\",\"children\":[{\"name\":\"子类目\"}]}；内容:"+content+"" +
                    "；分类json:"+classInfos;
//            promptsContent = "我需要你从三个分类中根据内容分析选一个最合适的，无需任何解释，你最多回答两个字，分类：工程、服务、货物；内容："+content;
        }else{
            promptsContent =  "我需要你将下面文章标题进行分类，这是一个标题：" +
                    content+" ，" +
                    "你只用回答属于什么分类即可,如果存在多个用“,”隔开并且每个分类保持在4字以内，回答字数控制在20字以内，无需解释";
        }

        return promptsContent;

    }

    /**
     * 分类信息json
     */
    public static class ClassEm{
        private String name;
        private List<TreeSelect> children = new ArrayList<TreeSelect>();

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public List<TreeSelect> getChildren() {
            return children;
        }

        public void setChildren(List<TreeSelect> children) {
            this.children = children;
        }
    }




    // 递归方法，用于查找节点并返回其子节点
    public static List<TreeSelect> findChildrenById(List<TreeSelect> nodes, Long id) {
        if (nodes == null) {
            return null;
        }
        for (TreeSelect node : nodes) {
            if (node.getId() == id) {
                return node.getChildren(); // 找到节点，返回其子节点
            }
            List<TreeSelect> children = findChildrenById(node.getChildren(), id);
            if (children != null) {
                return children; // 在子节点中找到，返回结果
            }
        }
        return null; // 没有找到节点
    }

    // 递归方法，用于查找节点并返回其子节点
    public static List<TreeSelect> findChildrenByLabel(List<TreeSelect> nodes, String label) {
        if (nodes == null) {
            return null;
        }
        for (TreeSelect node : nodes) {
            if (node.getLabel().equals(label) ) {
                return node.getChildren(); // 找到节点，返回其子节点
            }
            List<TreeSelect> children = findChildrenByLabel(node.getChildren(), label);
            if (children != null) {
                return children; // 在子节点中找到，返回结果
            }
        }
        return null; // 没有找到节点
    }

    /**
     * 生成任务
     * @param chatGPT
     * @param txtClassify
     * @return
     */
    public Map<String,Object> startGen(ChatGPT chatGPT,TxtClassify txtClassify,Map<String,Object> psMap){

        String useModelName = "";
        if(!ObjectUtils.isEmpty(psMap.get("model_conf"))){
            useModelName = String.valueOf(psMap.get("model_conf"));
        }else{
            useModelName = txtClassify.getModelName();
        }
        if(useModelName.contains("3.5")){
            List<String> molList = new ArrayList<String>();
            molList.add("gpt-3.5-turbo-1106");
//        molList.add("gpt-3.5-turbo-16k");
//        molList.add("gpt-3.5-turbo-16k-0613");
            molList.add("gpt-3.5-turbo");
            molList.add("gpt-3.5-turbo-0613");
            molList.add("gpt-3.5-turbo-0301");

            molList.add("gpt-3.5-turbo-0125");
            molList.add("gpt-3.5-turbo-16k");
            molList.add("gpt-3.5-turbo-16k-0613");


             useModelName = RandomUtil.randomEle(molList);
        }
        if(StringUtils.isEmpty(useModelName)){
            useModelName = "gpt-3.5-turbo";
        }

//        List<String> molList = new ArrayList<String>();
//        molList.add("gpt-3.5-turbo-1106");
//        molList.add("gpt-3.5-turbo-16k");
//        molList.add("gpt-3.5-turbo-16k-0613");
//        molList.add("gpt-3.5-turbo");
//        molList.add("gpt-3.5-turbo-0613");
//        molList.add("gpt-3.5-turbo-0301");
//        useModelName = RandomUtil.randomEle(molList);
//        System.out.println("使用模型："+useModelName);

                String content = txtClassify.getTxtContent();

//        String userPrompts = "我需要你将下面文章标题进行分类，这是一个法律协会发布的新闻标题：" +
//                content+" ，" +
//                "你只用回答属于什么分类即可,如果存在多个用“,”隔开并且每个分类保持在4字以内，回答字数控制在20字以内，无需解释";

        Boolean useClassItem = Boolean.valueOf(String.valueOf(psMap.get("useClassswitch")));
        List<TreeSelect> classInfos = (List<TreeSelect>)psMap.get("classinfo");

        Map<String,Object> map  = new HashMap<String,Object>();
        //token总数
        Integer tokenCount = 0;
        //提示词token
        Integer promptCount = 0;
        //输出词token
        Integer completionCount = 0;

        String classContent = "";

        //根据目前业务暂时支持三层
        String promptsContent = "";
        if(useClassItem){

            String topClass = String.valueOf(psMap.get("topClass"));
            //查询第一层
//            List<TreeSelect> topTree = findChildrenById(classInfos,0l);
            List<TreeSelect> topTree = findChildrenByLabel(classInfos,topClass);
            String treestr = getClassNames(topTree);
//            promptsContent = "我需要你根据我提供的分类信息的json， 将提供的内容进行分类,如果存在多级需要根据多级分类，不需要任何解释描述，" +
//                    "直接回答彼标准的层级json分类信息，选择最合适分类仅需两层级即可，" +
//                    "例如：{\"name\":\"主类目\",\"children\":[{\"name\":\"子类目\"}]}；内容:"+content+"" +
//                    "；分类json:"+classInfos;

            boolean hasChid =true;
            String thisNodestr = "";
            while (hasChid){

//                topTree = findChildrenByLabel(thisNodestr)
//                promptsContent = "我需要你从我提供的分类信息中根据内容分析选其中最合适的一个，无需任何解释，" +
//                        "只需回答分类名称即可；内容："+content+"；分类信息（多个/隔开）："+treestr;

                promptsContent = "分析内容，从我提供的分类信息中选择最合适的一个，无需任何解释，" +
                        "只需回答分类名称即可；内容：["+content+"]；  分类信息（用/隔开多个）：["+treestr+"]";
//                promptsContent = "分析内容["+content+"]；从分类信息（用/隔开多个）：["+treestr+"]  选择最合适的一个，只需要一个即可，无需任何解释，" +
//                        "只需回答分类名称即可；分类名不得超过17个汉字。 ";
                Message res =null;
                Message user =  Message.of(promptsContent);
                Message sys =  Message.ofSystem("你是一个内容分类专家");
                List messagesList =  Arrays.asList(sys,user);
                chatCompletion = ChatCompletion.builder()
                        .model(useModelName)
//                .model(txtClassify.getModelName())
//                    .model(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName())
//                    .messages(Arrays.asList(system,user))
                        .messages(messagesList)
//                    .maxTokens(GptHelper.calculateMaxToken(gptTopicTitle.getUseModel()))
                        .maxTokens(1000)
                        .temperature(0.9)
                        .build();
                ChatCompletionResponse response = chatGPT.chatCompletion(chatCompletion);
                tokenCount+=Integer.valueOf(String.valueOf(response.getUsage().getTotalTokens()));
                promptCount+=Integer.valueOf(String.valueOf(response.getUsage().getPromptTokens()));
                completionCount+= Integer.valueOf(String.valueOf(response.getUsage().getCompletionTokens()));
                res = response.getChoices().get(0).getMessage();
                thisNodestr = res.getContent();
                classContent += thisNodestr+">";
//                System.out.println(classContent+"=====分类名");
                topTree = findChildrenByLabel(classInfos,thisNodestr);
                if(ObjectUtils.isEmpty(topTree)){
                    hasChid  = false;
                    break;
                }
                treestr = getClassNames(topTree);
            }




        }

//        String userPrompts = getPrompts(content,psMap);



        logger.info("生成的分类：{}",classContent+"提示词："+promptsContent);
        map.put("classContent",classContent);
        map.put("tokenCount",tokenCount);
        map.put("promptCount",promptCount);
        map.put("completionCount",completionCount);
        map.put("useModelName",useModelName);
        return map;
    }

    /**
     *
     * 根据列表获取名字
     * @param treeList
     * @return
     */
    public String getClassNames( List<TreeSelect> treeList){
        String treestr = "";
        for(TreeSelect treeSelect:treeList){
            treestr+= treeSelect.getLabel()+"/";
        }
        if(treeList.size()>0){
            treestr = treestr.substring(0,treestr.length()-1);
        }
        return treestr;
    }



}
